import { Response } from 'express';
import { EventEmitter } from 'events';

interface SSEClient {
  id: string;
  deviceId: string;
  response: Response;
  lastPing: number;
  userAgent: string;
  capabilities: string[];
  messageCount: number;
}

export class SSEService extends EventEmitter {
  private clients: Map<string, SSEClient> = new Map();
  private deviceClients: Map<string, Set<string>> = new Map();
  private messageBuffer: Map<string, any[]> = new Map();
  private maxBufferSize = 100;

  // 连接管理
  connect(clientId: string, deviceId: string, res: Response, userAgent?: string): void {
    this.setupSSEResponse(res);
    
    const client: SSEClient = {
      id: clientId,
      deviceId,
      response: res,
      lastPing: Date.now(),
      userAgent: userAgent || '',
      capabilities: this.detectCapabilities(userAgent || ''),
      messageCount: 0
    };

    this.clients.set(clientId, client);
    this.addToDeviceGroup(deviceId, clientId);
    
    // 发送连接确认和离线消息
    this.sendConnectionConfirmation(clientId, deviceId);
    this.sendOfflineMessages(deviceId);
    
    // 设置连接监控
    this.setupConnectionMonitoring(clientId);
    
    console.log(`SSE连接建立: ${clientId} (设备: ${deviceId})`);
  }

  // 设置SSE响应头
  private setupSSEResponse(res: Response): void {
    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive',
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Headers': 'Cache-Control'
    });
  }

  // 发送消息到特定客户端
  sendToClient(clientId: string, event: string, data: any): void {
    const client = this.clients.get(clientId);
    if (client) {
      const message = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
      client.response.write(message);
      client.messageCount++;
      client.lastPing = Date.now();
    }
  }

  // 发送消息到设备的所有客户端
  sendToDevice(deviceId: string, event: string, data: any): void {
    const clientIds = this.deviceClients.get(deviceId);
    if (clientIds && clientIds.size > 0) {
      // 设备在线，直接发送
      clientIds.forEach(clientId => {
        this.sendToClient(clientId, event, data);
      });
    } else {
      // 设备离线，缓存消息
      this.bufferMessage(deviceId, event, data);
    }
  }

  // 广播消息到所有客户端
  broadcast(event: string, data: any): void {
    this.clients.forEach((client, clientId) => {
      this.sendToClient(clientId, event, data);
    });
  }

  // 消息缓冲
  private bufferMessage(deviceId: string, event: string, data: any): void {
    if (!this.messageBuffer.has(deviceId)) {
      this.messageBuffer.set(deviceId, []);
    }
    
    const buffer = this.messageBuffer.get(deviceId)!;
    const message = { event, data, timestamp: Date.now() };
    buffer.push(message);
    
    // 限制缓冲区大小
    if (buffer.length > this.maxBufferSize) {
      buffer.shift();
    }
  }

  // 发送离线消息
  private sendOfflineMessages(deviceId: string): void {
    const messages = this.messageBuffer.get(deviceId) || [];
    if (messages.length > 0) {
      console.log(`发送 ${messages.length} 条离线消息到设备 ${deviceId}`);
      messages.forEach(message => {
        const clientIds = this.deviceClients.get(deviceId);
        clientIds?.forEach(clientId => {
          this.sendToClient(clientId, message.event, message.data);
        });
      });
      this.messageBuffer.delete(deviceId);
    }
  }

  // 发送连接确认
  private sendConnectionConfirmation(clientId: string, deviceId: string): void {
    this.sendToClient(clientId, 'connection:established', {
      clientId,
      deviceId,
      timestamp: Date.now(),
      protocol: 'sse'
    });
  }

  // 智能重连支持
  private setupConnectionMonitoring(clientId: string): void {
    const client = this.clients.get(clientId);
    if (!client) return;

    // 心跳检测
    const heartbeatInterval = setInterval(() => {
      const client = this.clients.get(clientId);
      if (!client) {
        clearInterval(heartbeatInterval);
        return;
      }

      const now = Date.now();
      if (now - client.lastPing > 60000) { // 60秒超时
        this.disconnect(clientId);
        clearInterval(heartbeatInterval);
        return;
      }

      this.sendToClient(clientId, 'heartbeat', { timestamp: now });
    }, 30000);

    // 更新最后活动时间
    client.response.on('data', () => {
      if (client) {
        client.lastPing = Date.now();
      }
    });
  }

  // 能力检测
  private detectCapabilities(userAgent: string): string[] {
    const capabilities = [];
    
    if (userAgent.includes('Mobile')) {
      capabilities.push('mobile');
    }
    if (userAgent.includes('Chrome')) {
      capabilities.push('chrome-extension');
    }
    if (userAgent.includes('Firefox')) {
      capabilities.push('firefox-extension');
    }
    
    return capabilities;
  }

  // 添加到设备分组
  private addToDeviceGroup(deviceId: string, clientId: string): void {
    if (!this.deviceClients.has(deviceId)) {
      this.deviceClients.set(deviceId, new Set());
    }
    this.deviceClients.get(deviceId)!.add(clientId);
  }

  // 连接状态查询
  hasConnection(deviceId: string): boolean {
    const clientIds = this.deviceClients.get(deviceId);
    return clientIds ? clientIds.size > 0 : false;
  }

  // 获取设备的所有SSE连接
  getDeviceConnections(deviceId: string): string[] {
    const clientIds = this.deviceClients.get(deviceId);
    return clientIds ? Array.from(clientIds) : [];
  }

  // 断开客户端连接
  disconnect(clientId: string): void {
    const client = this.clients.get(clientId);
    if (client) {
      this.clients.delete(clientId);
      
      // 从设备分组中移除
      const deviceClients = this.deviceClients.get(client.deviceId);
      if (deviceClients) {
        deviceClients.delete(clientId);
        if (deviceClients.size === 0) {
          this.deviceClients.delete(client.deviceId);
        }
      }

      // 关闭响应流
      client.response.end();
      
      console.log(`SSE连接断开: ${clientId} (设备: ${client.deviceId})`);
    }
  }

  // 获取连接统计
  getConnectionStats() {
    return {
      totalClients: this.clients.size,
      deviceCount: this.deviceClients.size,
      bufferedMessages: Array.from(this.messageBuffer.entries()).map(([deviceId, messages]) => ({
        deviceId,
        messageCount: messages.length
      }))
    };
  }

  // 清理过期连接
  cleanup(): void {
    const now = Date.now();
    const expiredClients: string[] = [];

    this.clients.forEach((client, clientId) => {
      if (now - client.lastPing > 300000) { // 5分钟超时
        expiredClients.push(clientId);
      }
    });

    expiredClients.forEach(clientId => {
      this.disconnect(clientId);
    });

    if (expiredClients.length > 0) {
      console.log(`清理了 ${expiredClients.length} 个过期的SSE连接`);
    }
  }
} 